package com.dyh.quickdemozwei.thp_reactor;

import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Consumer;

/**
 * @Author: yhdong
 * @Date: 2021/11/16 10:06
 */
@Slf4j
public class Reactor1116_1 {

    private Map<String, Reactor1112_1.Node> nodeMap = new HashMap<>();

    public <T> void applyKenel(String code, List<T> tasks, Consumer doneConsumer){
        Reactor1112_1.Node node = nodeMap.get(code);
        if (node==null)
            return;

        node.getTasksQueue().addAll(tasks);
    }

    public class SelectThread extends Thread{
        @SneakyThrows
        @Override
        public void run() {
            for (;;){

                pullTask();

                for (Map.Entry<String, Reactor1112_1.Node> entry : nodeMap.entrySet()) {
                    Reactor1112_1.Node node = entry.getValue();
                    if ( checkAllRuned(node.getCtrl())){
                        log.info("{} selected",Thread.currentThread().getName());
                        if (node.getDoneConsumer()!=null){
                            node.getDoneConsumer().accept(null);
                            node.setDoneConsumer(null);
                        }
                        resetInit(node.getCtrl());
                    }
                }
                Thread.sleep(500L);
            }
        }

        private void pullTask() {
            for (Map.Entry<String, Reactor1112_1.Node> entry : nodeMap.entrySet()) {
                Reactor1112_1.Node node = entry.getValue();
                int offset = Math.min(node.getTasksQueue().size(),32);

                for (int i = 0;i<offset;i++){

                }

            }
        }
    }


    boolean checkAllRuned( byte[] ctrl){
        for (byte b : ctrl) {
            if (b==0)
                return false;
        }
        return true;
    }

    boolean checkAllInit( byte[] ctrl){
        for (byte b : ctrl) {
            if (b==1)
                return false;
        }
        return true;
    }

    void resetInit(byte[] ctrl){
        for (int i = 0; i<ctrl.length;i++){
            ctrl[i]=0;
        }

    }

    @Setter
    @Getter
    public static class Node<T>{
        String code;
        Consumer<T> consumer;
        Consumer<T> doneConsumer;
        ThreadPoolExecutor poolExecutor;
        int maxBatch;
        volatile int startCtrl;
        volatile int endCtrl;

        LinkedList tasksQueue = new LinkedList();

        public Node(String code, Consumer<T> consumer, ThreadPoolExecutor poolExecutor) {
            this.code = code;
            this.consumer = consumer;
            this.poolExecutor = poolExecutor;
        }

    }
}
